package com.beta.resource.model;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.beta.resource.mapper.CategoryMapper;
import com.beta.resource.mapper.CodeFileMapper;
import com.beta.resource.utils.BaseString;
import com.beta.resource.utils.onStatusChange;

public class UserEnv {
    public static final String DEFAULT_CODE_TITLE = "Code Editor";
    public static final String CATEGORY_DEFAULT = "Default";
    public static final String CATEGORY_DRAFT = "Draft";
    private static final int PREVIOUS_PAGE_INDEX = -1;
    private static final int NEXT_PAGE_INDEX = -2;
    
    private int mUID;
    private UserInfo mInfo;

    public UserEnv(UserInfo info){
        mInfo = info;
        mUID = mInfo.getUid();
    }

    public String getAuthorID(String prefix) {
        return String.format("%s_%d", prefix, mUID);
    }

    public UserEnv updateInfo(UserInfo info){
        mInfo.copy(info);
        return this;
    }

    public UserInfo getInfo(){
        return mInfo;
    }

    public int getUID(){
        return mUID;
    }

    public String getPageTitle(String title, String prefix) {
        return title + " - " + getAuthorID(prefix);
    }

    public UserFile getDefaultUserFile(String title, String desc) {
        UserFile file = new UserFile();
        file.setDesc(desc);
        file.setTitle(title);
        return file;
    }

    public List<Category> getCategories(CategoryMapper categoryMapper, boolean encode) {
        List<Category> list = categoryMapper.getCategoryList(mUID);
        Category category;
        if (list.isEmpty()) {
            category = new Category();
            if (encode) {
                category.desc = BaseString.encodeBase64(CATEGORY_DRAFT, CATEGORY_DRAFT);
            } else {
                category.desc = CATEGORY_DRAFT;
            }
            list.add(category);
            category = new Category();
            if (encode) {
                category.desc = BaseString.encodeBase64(CATEGORY_DEFAULT, CATEGORY_DEFAULT);
            } else {
                category.desc = CATEGORY_DEFAULT;
            }
            list.add(category);
        }
        return list;
    }

    public List<UserFile> getCodeFiles(CategoryMapper categoryMapper, CodeFileMapper codeFileMapper, String categoryDesc, int offset, int itemnum) {
        Category category = categoryMapper.getCategory(categoryDesc);
        List<UserFile> list = null;
        if(category != null){
            list = codeFileMapper.getCodeFiles(mUID, category.getId(), offset * itemnum,
                offset * itemnum + itemnum);
        }
        return list;
    }

    public int getRemainingFiles(int offset, CodeFileMapper codeFileMapper, int itemnum) {
        Integer count = codeFileMapper.getFoundRows();
        if(count == null){
            return 0;
        }
        return Math.max(0, count.intValue() - (offset * itemnum));
    }

    public UserFile loadFile(int fid, CodeFileMapper codeFileMapper, onStatusChange listener, Object data) throws IOException {
        UserFile file = codeFileMapper.getFileInfo(fid, mUID);
        if(file != null && listener != null){
            file.read(listener, data);
        }
        return file;
    }

    public int saveFile(UserFile file, CategoryMapper categoryMapper, CodeFileMapper codeFileMapper, String savedir, String notes) {
        Category category = categoryMapper.getCategory(file.getCategory());
        if (category == null) {
            category = new Category();
            category.setDesc(file.getCategory());
            categoryMapper.addCategory(category);
        }
        if(categoryMapper.hasCategory(mUID, category.id) == 0){
            categoryMapper.addCategoryFor(mUID, category.id);
        }
        file.preSave(savedir, mUID, category.id, file.isNewOne(), notes);
        if (file.isNewOne()) {
            file.setId(codeFileMapper.saveFile(file));
        } else {
            codeFileMapper.updateFile(file);
        }
        return file.getId();
    }

    public List<Page> calcCurrentPage(int start, int index, int remaining, int pagenum, int itemnum) {
        List<Page> pages = new ArrayList<>();
        if (index == PREVIOUS_PAGE_INDEX) {
            start -= 1;
            index = 0;
        } else if (index == NEXT_PAGE_INDEX) {
            start += 1;
        }
        int count = (remaining / itemnum + (remaining % itemnum > 0 ? 1 : 0));
        if (index == NEXT_PAGE_INDEX) {
            index = Math.min(count, pagenum);
        }
        if (start > 1) {
            pages.add(new Page("<").setIndexNum(PREVIOUS_PAGE_INDEX).setStartNum(start));
        }
        for (int i = 0; i < Math.min(count, pagenum); i++) {
            pages.add(new Page(String.valueOf(i + start)).setActive(index == (i + start)).setIndexNum(i + start)
                    .setStartNum(start));
        }
        if (count > pagenum) {
            pages.add(new Page(">").setIndexNum(NEXT_PAGE_INDEX).setStartNum(start));
        }
        return pages;
    }
}